package fun.coding.effective.java;

import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import fun.coding.effective.java.Period.PeriodTimeException;

public class EffectiveJava {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Date start = new Date(10);
		Date end = new Date();
		try {
			Period p = new Period(start, end);
			// This line will hack the check in the constructor, thus need to make defensive copy. 
			end.setDate(1);
		} catch(PeriodTimeException e) {
			e.printStackTrace();
		}

		System.out.println("Done...");
		System.out.println(EffectiveJava.class.getSimpleName());

		// java assertion needs to be enabled so that AssertionError will be thrown. 
		int m = 10;
		assert m < 0;

		int a0 = 5;
		int a1 = 10;

		int a2 = a1--;
		int a3 = --a1;
		// a0-- is not executed, so it should not decrease.
		int a4 = a1 > a0 ? --a1 : a0--;
		System.out.println("a2 is " + a2 + " a3 is " + a3 + " a0 is " + a0);

		List<String> s = new LinkedList<String>();
		s.add("xiaoyu shi");
		s.add("Xiaowen ding");
		s.add("Yuxing yao");

		Collections.sort(s, String.CASE_INSENSITIVE_ORDER);

		System.out.println(Arrays.asList(s));

		// Hooray, now I completely understand how java handles equals and ==
		// equals compares the content while == compares the references
		// s2 = s1 == will return true because in Java string are immutable and created in the JVM perm stack, it is sharing the same reference
		// while new String(); is creating a new reference thus == will return false
		// However, according to effective java, almost everytime you see new String() would be wrong since you don't need to b/c strings are immutable.
		String s1 = "foo";
		String s2 = s1;
		// almost always wrong. 
		String s3 = new String("foo");

		if(s1.equals(s3)) {
			System.out.println("equal");
		} else {
			System.out.println("Not equal");
		}

		if(s1 == s3) {
			System.out.println("==");
		} else {
			System.out.println("Not ==");
		}
		
		Integer aa = new Integer(100);
		testParams(aa);
		System.out.println(aa);
		
		int a;
		int b = 3;
		// cannot assign double to int, need force type conversion. 
		a = (int)Math.pow(2, b);
		System.out.println(a);
		
		int c = (b++);
		System.out.println("c is " + c);
	}
	
	
	@Override
	public boolean equals(Object arg0) {
		return super.equals(arg0);
	};

	// Carvet 1, hashCode and equals are friends, they should always been overriden together to make the object consistent or else when you add 
	// them to collections, it will cause problems. 
	// Carvet 2, hashCode is an easier way to compare if two objects are the same instead of .equals to compare each item one by one. 
	@Override
	public int hashCode() {
		return super.hashCode();
	}
	
	/*http://blog.csdn.net/zhiyu27/article/details/8186372
	 * Java uses references for all variables, but it always passes by value, passing by reference is also by value, think about 
	 * making a new copy of the reference or pointer. 
	 * 
	 * Java manipulates objects 'by reference,' but it passes object references to methods 'by value
	 * */
	public static void testParams(Integer a) {
	    a = 9;
	}

}
